package com.zx._02_thread.线程池;

import com.zx.common.util.ThreadUtil;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;

/**
 * @version v1.0
 * @Project: knowledge
 * @Title: 线程池被如何被爆
 * @Description: 演示阿里为啥不推荐使用jdk默认的连接池
 * @author: zhangxue
 * @date: 2020年5月8日下午9:16:50
 * @company: 未知
 * @Copyright: Copyright (c) 2015
 */
@Slf4j
public class 线程池被如何被爆 {

    //设置jvm参数： -Xmx12m -Xms12m -Xmn4m -Xss128k -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError
    public static void main(final String[] args) throws Exception {
        // 1. 比较普通的线程池使用，其中线程池满后，后面提交的任务被丢地
        // 下面的线程池演示的是 Executors.newFixedThreadPool(10); 最后的淘汰策略根本使用不上
        final ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
                线程池被如何被爆.log.info("线程池已满，任务被淘汰");
            }
        });

        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            final int idx = i;
            pool.execute(() -> {
                log.info("线程编号={}", idx);
                ThreadUtil.sleep(10);

            });
            if (i % 10000 == 0) {
                // 当前运行的任务数
                final int activeCount = pool.getActiveCount();
                // 队列中的任务数
                final int queueSize = pool.getQueue().size();
                // 全部的任务数
                final long taskCount = pool.getTaskCount();
                // 全部完成的任务书
                final long completedTaskCount = pool.getCompletedTaskCount();
                log.info("线程监控, activeCount={}, queueSize={}, taskCount={}, completedTaskCount={}", activeCount,
                        queueSize, taskCount, completedTaskCount);
            }
        }
		/*	最终内存溢出，意思是，jvm回收对象，但是多次gc，大部分的时间只回收了很少的对象。
			Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
			at java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:416)
		*/
    }


}
